package org.umss.fixture.services;

import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;

import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.protocol.HTTP;

import android.util.Log;

/**
 * This class make a connection beetwen the server and the android app to get a
 * JSON string with the needed data.
 * 
 * @author Daniela Meneses
 * 
 */
public class Connection {
	/**
	 * Needed URI to make the connection with the server. This URI shouldn't
	 * contain the name of a service only the path to get that resource.
	 */
	private String serverAddress;

	/**
	 * Constructor to initialize the URI atribute.
	 * 
	 * @param URI
	 *            Selected URI to make the connections.
	 */
	public Connection(String URI) {
		serverAddress = URI;
	}

	/**
	 * Method that make a GET call to a rest service and returns the JSON string
	 * response from the called rest service.
	 * 
	 * @param pathName
	 *            The path of the rest service
	 * @return JSON string response
	 * @throws ConnectionException
	 */
	public String get(String pathName) throws ConnectionException {
		return get(pathName, null);
	}

	/**
	 * Method that make a GET call to a rest service and returns the JSON string
	 * response from the called rest service including parameters.
	 * 
	 * @param pathName
	 *            The path of the rest service.
	 * @param params
	 *            Parameters to be added to the request.
	 * @return JSON string response
	 * @throws ConnectionException
	 */
	public String get(String pathName, ArrayList<NameValuePair> params)
			throws ConnectionException {
		String res = null;
		HttpURLConnection connection = null;
		try {
			URL url;
			if (params != null) {
				String parameters = buildParameters(params);
				url = new URL(serverAddress + pathName + "?" + parameters);
			} else {
				url = new URL(serverAddress + pathName);
			}
			Log.i("URL", url.toString());

			connection = (HttpURLConnection) url.openConnection();
			connection.setRequestProperty("charset", "utf-8");
			connection.setConnectTimeout(10000);
			connection.connect();

			if (connection.getResponseCode() == 200) {
				res = getASCIIContentFromEntity((InputStream) connection
						.getContent());
			} else {
				int code = connection.getResponseCode();
				throw new ConnectionException(code);
			}
			connection.disconnect();
		} catch (MalformedURLException e) {
			throw new ConnectionException(e);
		} catch (IOException e) {
			throw new ConnectionException(e);
		}

		return res;
	}

	/**
	 * Parse the response contained in HttpEntity to the JSON string.
	 * 
	 * @param input
	 *            Response to parse.
	 * @return JSON String with the parsed response.
	 * @throws IllegalStateException
	 * @throws IOException
	 */
	private String getASCIIContentFromEntity(InputStream input)
			throws IllegalStateException, IOException {
		InputStream in = input;
		StringBuffer out = new StringBuffer();
		int n = 1;

		while (n > 0) {
			byte[] b = new byte[4096];
			n = in.read(b);
			if (n > 0)
				out.append(new String(b, 0, n));
		}

		return out.toString();
	}

	/**
	 * Method that make a POST call to a rest service with parameters and
	 * returns the JSON string response from the called rest service.
	 * 
	 * @param pathName
	 *            The path of the rest service.
	 * @param postParameters
	 *            Parameters for the POST method.
	 * @return JSON string response
	 * @throws ConnectionException
	 */
	public String post(String pathName, ArrayList<NameValuePair> postParameters)
			throws ConnectionException {
		String res = null;
		try {
			String parameters = buildParameters(postParameters);
			URL url = new URL(serverAddress + pathName);
			HttpURLConnection connection = (HttpURLConnection) url
					.openConnection();
			connection.setDoOutput(true);
			connection.setDoInput(true);
			connection.setInstanceFollowRedirects(false);
			connection.setRequestMethod(HttpPost.METHOD_NAME);
			connection.setRequestProperty("Content-Type",
					"application/x-www-form-urlencoded");
			connection.setRequestProperty("charset", "utf-8");
			connection.setRequestProperty("Content-Length",
					"" + Integer.toString(parameters.getBytes().length));
			connection.setUseCaches(false);

			DataOutputStream wr = new DataOutputStream(
					connection.getOutputStream());
			wr.writeBytes(parameters);
			wr.flush();
			wr.close();
			connection.disconnect();

			if (connection.getResponseCode() == 200) {
				res = getASCIIContentFromEntity((InputStream) connection
						.getContent());
			} else {
				int code = connection.getResponseCode();
				throw new ConnectionException(code);
			}
			connection.disconnect();
		} catch (MalformedURLException e) {
			throw new ConnectionException(e);
		} catch (IOException e) {
			throw new ConnectionException(e);
		}

		return res;
	}

	public String buildParameters(ArrayList<NameValuePair> params) {
		String res = "";
		NameValuePair pair = null;
		for (int i = 0; i < params.size(); i++) {
			pair = params.get(i);
			res += pair.getName() + "=" + pair.getValue();
			if (params.size() - 1 != i) {
				res += "&";
			}
		}

		return res;
	}

	public void postPayload(String pathName, String json) {
		DefaultHttpClient httpclient = new DefaultHttpClient();
		HttpPost httppostreq = new HttpPost(serverAddress + pathName);
		httppostreq.setHeader("Accept", "application/json");
		httppostreq
				.setHeader("Content-type", "application/json; charset=utf-8");
		try {
			StringEntity stringEntity = new StringEntity(json, HTTP.UTF_8);
			httppostreq.setEntity(stringEntity);
			HttpResponse httpresponse = httpclient.execute(httppostreq);
			httpresponse.getStatusLine().getStatusCode();
		} catch (ClientProtocolException e) {
			Log.w("ClientProtocolException", e.getMessage());
		} catch (IOException e) {
			Log.w("IOException", e.getMessage());
		}
	}
}
